import { existsSync, writeFileSync } from 'fs';
import { dirname, join } from "path";
import { IWriter, ITableOutput } from "../../inters/InterfaceApi";
import { mkdirsSync } from '../../utils/CpFile';
import { ICls, IInterface, newLine } from '../utils/ClsFactory';
import { codeMgr } from '../mgr/CodeMgr';

export class CsWriter implements IWriter {

    private _cfg: ITableOutput;

    // 直接把ts翻译成了cs，方便！
    private _convetTs2Cs(ts: string, pkey: string = ""): string {
        let out = "";
        let list = ts.split("\r\n");
        let crtType = "";
        list.forEach(t => {
            if (t.substr(0, 5) == "enum ") {
                t = t.replace("enum ", "public enum ");
                crtType = "enum";
            } else if (t.substr(0, 6) == "const ") {
                t = t.replace("const ", "public class ");
                t = t.replace("=", "");
                crtType = "const";
            } else if (t.substr(0, 10) == "interface ") {
                t = t.replace("interface ", "public class ");
                if (!!pkey)
                    t = t.replace("{", ": ISysMainKey {");
                crtType = "interface";
            } else if (t.substr(0, 1) == "}") {
                if (crtType == "interface" && !!pkey) {
                    // 如果是类的话，这里插入一行mainkey
                    t = `\tpublic string MainKey{get=>${pkey}.ToString();}\n}`
                }
                crtType = "";
            }
            if (crtType == "const") {
                let ctemp = t.split(":");
                if (ctemp.length > 1) {
                    let ctidx = ctemp[1].lastIndexOf(",");
                    let ct1 = ctemp[1];
                    if (ctemp[1].substr(ctidx, 1) == ",") {
                        ct1 = ctemp[1].substr(0, ctidx) + ";" + ctemp[1].substr(ctidx + 1);
                    }
                    if (ct1.substr(0, 1) == '"') {
                        // 字符串
                        t = "\tpublic static string " + ctemp[0] + " = " + ct1;
                    } else {
                        t = "\tpublic static int " + ctemp[0] + " = " + ct1;
                    }
                }
            } else if (crtType == "interface") {
                let ctemp = t.split("?:");
                if (ctemp.length > 1) {
                    if (ctemp[1].indexOf("[]") > 0) {
                        // 列表
                        let tidx = ctemp[1].indexOf("[]");
                        let ctemp1 = ctemp[1].substr(0, tidx);
                        t = "\tpublic List<" + ctemp1 + "> " + ctemp[0] + ";";
                    } else if (ctemp[1].indexOf("Array<") >= 0) {
                        // 列表
                        let ctemp1 = ctemp[1].replace("Array", "List")
                        ctemp1 = ctemp1.replace(";", "");
                        t = "\tpublic " + ctemp1 + " " + ctemp[0] + ";";
                    } else {
                        let ctemp1 = ctemp[1].replace(";", "");
                        t = "\tpublic " + ctemp1 + " " + ctemp[0] + ";";
                    }
                }
            }
            out += (t + "\r\n");
        });

        return out;
    }
    write(data: any, options?: any, callback?: (res?: any) => void) {
        this._cfg = data;

        let dts = "";
        let clsHash = {};
        let dtsList = codeMgr.dtsList;

        dtsList.forEach(ts => {
            if (clsHash[ts.name]) return;
            let temp = ts.toString();
            let pkey = "";
            if (ts instanceof IInterface) {
                pkey = ts.getPrimaryKey();
            }
            temp = this._convetTs2Cs(temp, pkey);

            dts += (temp + newLine + newLine);

            clsHash[ts.name] = 1;
        })
        let opPath: string[]
        if (typeof this._cfg.path == 'string') {
            opPath = [this._cfg.path];
        } else {
            opPath = this._cfg.path
        }
        // let path = options.path;
        opPath.forEach(p => {
            let dir = p;//join(path, p);
            if (!existsSync(dir)) {
                mkdirsSync(dir);
            }
            let mainkey = `public interface ISysMainKey { string MainKey { get; } }\n`
            let str = this._cfg.fileStart + mainkey + dts + this._cfg.fileEnd;

            writeFileSync(join(dir, `${this._cfg.fileName}.${this._cfg.type}`), str);
        })

        if (!!callback) callback();
    }

}